package com.mfhcd.facepay.activity

import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Rect
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.RemoteException
import android.text.TextUtils
import android.util.Log
import android.view.Gravity
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager
import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.google.gson.Gson
import com.jakewharton.rxbinding3.view.clicks
import com.landi.finance.face.aidl.constant.CameraConstant
import com.landi.finance.face.aidl.constant.ParamKey
import com.landi.finance.face.aidl.constant.ScreenConstant
import com.landi.finance.face.aidl.listener.OnResultListener
import com.mfhcd.facepay.App
import com.mfhcd.facepay.R
import com.mfhcd.facepay.adapter.GridKeyboardAdapter
import com.mfhcd.facepay.base.BaseActivity
import com.mfhcd.facepay.constant.ArouterUrl
import com.mfhcd.facepay.databinding.ActivityPaymentBinding
import com.mfhcd.facepay.model.RequestModel
import com.mfhcd.facepay.model.ResponseModel.TransResp
import com.mfhcd.facepay.model.ResponseModel.TrxDataResp
import com.mfhcd.facepay.model.TitleBean
import com.mfhcd.facepay.model.TypeModel
import com.mfhcd.facepay.utils.*
import com.mfhcd.facepay.viewmodel.TestViewModel
import com.mfhcd.facepay.widget.PayPasswodInput
import org.apaches.commons.codec.binary.Base64
import per.goweii.anylayer.DialogLayer
import per.goweii.anylayer.Layer
import per.goweii.anylayer.Layer.OnShowListener
import java.io.File
import java.io.FileOutputStream
import java.text.DecimalFormat
import java.text.NumberFormat
import java.util.*
import java.util.concurrent.TimeUnit


@Route(path = ArouterUrl.ACTIVITY_PAYMENT)
class PaymentActivity : BaseActivity<TestViewModel, ActivityPaymentBinding>() {

    private lateinit var keys: MutableList<TypeModel>
    private lateinit var mAdapter: GridKeyboardAdapter
    private lateinit var stringBuffer: StringBuffer
    private lateinit var inputData: String
    private lateinit var coordinate: String

    companion object {
        const val TYPE_LABEL = "type_label"
        const val TYPE_TRANS = "type_trans"
        const val TYPE_PRE_AUTH = "type_pre_auth"
    }

    @Autowired(name = TYPE_LABEL)
    lateinit var transType: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_payment)
        mBaseBinding.titleBean = TitleBean("收款")
        LogUtil.d("当前交易类型是：$transType")
    }

    override fun initData() {
        keys = ArrayList<TypeModel>()
        var keyBoard: TypeModel? = null
        for (i in 0..11) {
            keyBoard = TypeModel()
            if (i + 1 == 10) {
                keyBoard.dkey = "00"
            } else if (i + 1 == 11) {
                keyBoard.dkey = "0"
            } else if (i + 1 == 12) {
                keyBoard.dkey = "←"
            } else {
                keyBoard.dkey = ((i + 1).toString())
            }
            keyBoard.dvalue = (i.toString())
            keys.add(keyBoard)
        }

        initGridKeys()

        viewModel.locationInfo.observe(
                this,
                Observer { location ->
                    run {
                        coordinate = "${location.latitude}/${location.longitude}"
                        LogUtil.d("coordinate:$coordinate")
                    }
                }
        )
    }

    @SuppressLint("CheckResult")
    override fun initListener() {
        mAdapter.setOnItemClickListener { adapter, view, position ->
            keyBoardClick(position)
        }
        bindingView.btnAction.clicks()
                .throttleFirst(1, TimeUnit.SECONDS)
                .subscribe {
                    /*点击确认收款操作逻辑：
                    1、确认输入金额
                    2、发起检查是否绑定服务，没有绑定则重新发起绑定并延迟一秒在此执行操作
                    3、发起人脸识别
                    4、输密码
                    5、发起路由请求
                    6、发起数据上送，根据返回结果判断是否需要输入手机号后四位
                    7、上送完整交易数据*/
                    var inputAmountString: String = bindingView.tvInputAmount.text.toString()
                    LogUtil.d("输入原始金额:$inputAmountString")
                    var inputAmount = inputAmountString.replace("￥：", "")
                    if (TextUtils.isEmpty(inputAmountString) || "0.00".equals(inputAmount)) {
                        ToastUtil.showToast("请先输入收款金额")
                        return@subscribe
                    }
//                    LogUtil.d("最终输入金额:$inputAmount")
                    // 发起人脸识别
                    if (App.getFaxeService() != null) {
                        Handler().post(detectFace(inputAmount))
                    } else {
                        App.getInstance().bindFacePay()
                        Handler().postDelayed(detectFace(inputAmount), 1000)
                    }
                    // 直接发起交易
//                    doTransaction(amountToFen(inputAmount))
                }
    }

    private fun initGridKeys() {
        val gridLayoutManager = GridLayoutManager(mContext, 3)
        bindingView.rvKeyboard.layoutManager = gridLayoutManager
        mAdapter = GridKeyboardAdapter(mContext, keys)
        bindingView.rvKeyboard.adapter = mAdapter
    }

    /**
     * 输入键盘点击
     *
     * @param position
     */
    private fun keyBoardClick(position: Int) {
        var type = 0
        if (position == 11) { /*删除键*/
            type = -1
        }
        stringBuffer = StringBuffer()
        // 获取文本框显示的字符串
        var input: String = bindingView.tvInputAmount.text.toString()
        input = input.replace("￥：", "").replace(",", "").replace(".", "")
        stringBuffer.append(input)
        inputData = keys[position].dkey
        inputData(inputData, type)
    }

    /**
     * 转化点击输入内容
     */
    private fun inputData(data: String, type: Int) {
        var result1: String
        when (type) {
            0 -> {
                result1 = formatSum(data)
                if (!TextUtils.isEmpty(result1)) {
                    val sumMoney = result1.replace("￥：", "").trim { it <= ' ' }
                    Log.i("money", "==============sumMoney==============:$sumMoney")
                    // 10包含1位逗号和一个小数点
                    if (sumMoney.length > 8 + 2) {
                        DialogUtils.showConfirmDialog(mContext, getString(R.string.prompt), getString(R.string.trade_amount_overrun))
                        return
                    }
                }
                bindingView.tvInputAmount.text = (result1)
            }
            -1 -> backspaceData()
            else -> {
            }
        }
    }

    /**
     * 格式化输入数字
     *
     * @param data
     */
    private fun formatSum(data: String): String {
        var result: String = ""
        stringBuffer.append(data)
        result = if (stringBuffer.length == 0) {
            "￥：0.00"
        } else if (stringBuffer.length == 1) {
            "￥：0.0$stringBuffer"
        } else if (stringBuffer.length == 2) {
            "￥：0.$stringBuffer"
        } else {
            returnResult()
        }
        return result
    }


    /**
     * 清除数据
     */
    fun clearData() {
        if (stringBuffer != null) {
            stringBuffer.delete(0, stringBuffer.length)
            bindingView.tvInputAmount.text = ("￥：0.00")
        }
    }

    /**
     * 回删数据
     */
    private fun backspaceData() {
        val string = stringBuffer.toString().replace(".", "").trim { it <= ' ' }
        if (string != null && "" != string && string.length != 0) {
            clearData()
            stringBuffer.append(string)
            stringBuffer.deleteCharAt(stringBuffer.length - 1)
            val result = returnResult()
            bindingView.tvInputAmount.text = result
        }
    }

    /**
     * 金额格式
     *
     * @param s   金额
     * @param len 小数位数
     * @return 格式后的金额
     */
    fun formatMoney(s: String?, len: Int): String {
        if (s == null || s.length < 1) {
            return ""
        }
        var formater: NumberFormat? = null
        val num = s.trim { it <= ' ' }.toDouble()
        formater = if (len == 0) {
            DecimalFormat("###,###")
        } else {
            val buff = StringBuffer()
            buff.append("###,###.")
            for (i in 0 until len) {
                buff.append("#")
            }
            DecimalFormat(buff.toString())
        }
        return formater.format(num)
    }

    /**
     * 返回结果
     */
    private fun returnResult(): String {
        var result = ""
        var temp = stringBuffer.toString()
        temp = temp.replace(".", "")
        stringBuffer.delete(0, stringBuffer.length)
        stringBuffer.append(temp)
        var length = stringBuffer.length
        // stringBuffer=stringBuffer.
        if (length == 0) {
            stringBuffer.insert(0, "0")
            length += 1
        }
        if (length == 1) {
            stringBuffer.insert(0, "0")
            length += 1
        }
        try {
            result = stringBuffer.insert(length - 2, ".").toString()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        result = "￥：" + formatMoney(result, 2)
        val indexOf = result.indexOf(".") + 1
        if (indexOf == 0) {
            result += ".00"
        } else {
            val substring = result.substring(indexOf)
            if (substring.length == 1) {
                result += "0"
            }
        }
        return result
    }

    /**
     * @param inputAmount 交易金额
     */
    private fun detectFace(inputAmount: String): Runnable {
        return Runnable {
            val param = Bundle()
            param.putInt(ParamKey.KEY_CAMERAID, CameraConstant.EXTERNAL)
            //            param.putInt(ParamKey.KEY_VOICE_VOLUME, 20);
            param.putString(ParamKey.KEY_AMOUNT, "${inputAmount}元")
            param.putBoolean(ParamKey.KEY_CONFIRM_FACE, true)
            param.putBoolean(ParamKey.KEY_BACK_CAMERA_MIRROR, true)
            param.putBoolean(ParamKey.KEY_VOICE_PROMPT, true)
            param.putBoolean(ParamKey.KEY_AUTO_FLASH_LIGHT, true)
            param.putBoolean(ParamKey.KEY_ALIVE, true)
            param.putInt(ParamKey.KEY_PREVIEW_SCREEN, ScreenConstant.INDEXT_MAIN_SCREEN)
            param.putInt(ParamKey.KEY_TIMEOUT, 30)
            try {
                App.getFaxeService().detectFace(param, object : OnResultListener.Stub() {
                    @Throws(RemoteException::class)
                    override fun onSuccess(result: Bundle) {
                        runOnUiThread {
                            val b: ByteArray? = result.getByteArray(ParamKey.KEY_IMAGE_DATA)
                            var bitmap = BitmapFactory.decodeByteArray(b, 0, b!!.size)
                            var info = "图片宽高：" + bitmap.width + "x" + bitmap.height + "; \n图片大小：" + b.size / 1024 + "K"
                            if (result.containsKey(ParamKey.KEY_FACE_RECT)) {
                                val rect: IntArray? = result.getIntArray(ParamKey.KEY_FACE_RECT)
                                info += "\nleft = " + rect!![0] + " top = " + rect[1] + " right = " + rect[2] + " bottom = " + rect[3]
                                bitmap = cropBitmapByRect(bitmap, Rect(rect[0], rect[1], rect[2], rect[3]))
                            }
                            try {
                                val file = File("/sdcard" + File.separator + "cameraSuccess")
                                if (!file.exists() || !file.isDirectory) {
                                    file.mkdir()
                                }
                                val mTempPhotoPath = file.path + File.separator + System.currentTimeMillis() + ".jpg"
                                val mFile = File(mTempPhotoPath)
                                val outStream = FileOutputStream(mFile)
                                outStream.write(b)
                                outStream.flush()
                                outStream.close()
                                val intent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
                                intent.data = Uri.fromFile(mFile)
                                sendBroadcast(intent)
                            } catch (e: Exception) {
                                e.printStackTrace()
                            }
                            bindingView.ivBg.setImageBitmap(bitmap)
                            bindingView.tvResult.text = "人脸识别结果展示区域：\n$info"

                            // 封装请求参数
                            var tempByte = BitmapUtils.getBitmapByte(bitmap)
                            var stringData = String(Base64.encodeBase64(tempByte))

                            var transAmount = amountToFen(inputAmount)

                            //弹框输密码
                            showPwdInputDialog(stringData, transAmount)
                        }
                    }

                    @Throws(RemoteException::class)
                    override fun onError(code: String, message: String) {
                        runOnUiThread { ToastUtil.showLongToast("[$code]$message") }
                    }
                })
            } catch (e: RemoteException) {
                e.printStackTrace()
            }
        }
    }

    /**
     * 金额转化为分：12位，不足位补零
     */
    private fun amountToFen(inputAmount: String): String {
        var transAmount = inputAmount.replace(".", "")
        //12位以分为单位
        var zeroPlaceholder = StringBuilder()
        for (i in 0 until 12 - transAmount.length) {
            zeroPlaceholder.append("0")
        }
        zeroPlaceholder.append(transAmount)
        return zeroPlaceholder.toString()
    }


    /**
     * 金额转化为分：12位，不足位补零
     */
    private fun amountToYuan(amountFen: String): String {
        var transAmount = amountFen.toDouble() / 100
        return transAmount.toString()
    }

    /**
     * 通过人脸框坐标截取全景图上的最佳人脸
     *
     * @param srcBitmap 全景图
     * @param rect      人脸坐标
     * @return
     */
    fun cropBitmapByRect(srcBitmap: Bitmap?, rect: Rect): Bitmap? {
        val mBitmapShow: Bitmap
        if (srcBitmap == null) {
            return null
        }
        mBitmapShow = try {
            Bitmap.createBitmap(srcBitmap,
                    rect.left,
                    rect.top,
                    Math.abs(rect.right - rect.left),  // 要裁剪的宽度
                    Math.abs(rect.bottom - rect.top)) // 要裁剪的高度
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            return null
        }
        return mBitmapShow
    }

    /**
     * 密码输入弹框
     * @param stringData 人脸识别base64数据
     * @param transAmount 交易上送金额
     */
    private fun showPwdInputDialog(stringData: String, transAmount: String) {
        var pwdInput: PayPasswodInput? = null
        val dialogLayer: DialogLayer = DialogUtils.showViewDialog(mContext, R.layout.layout_dialog_pwd_input, Gravity.CENTER)
        dialogLayer.cancelableOnTouchOutside(true)
                .onClick(Layer.OnClickListener { layer, v ->
                    run {
                        LogUtil.d("付款")
                        layer.dismiss()
                        val input = pwdInput!!.editText!!.text
                        LogUtil.d("输入密码为:$input")

                        var requestParas = initRequestParams(1)
                        requestParas.pin = "$input"
                        requestParas.trx_amt = transAmount
                        requestParas.pic = stringData
                        var jsonString = Gson().toJson(requestParas)
                        viewModel.faceRouter(requestParas).observe(this@PaymentActivity, Observer { resp: TrxDataResp ->
                            run {
                                LogUtil.d(Convert.toJson(resp))
//                                resp.code = "1000"
                                when (resp.code) {
                                    "1000" -> {
                                        LogUtil.d("需要输入手机号后四位")
                                        showPhoneNoInputDialog(requestParas)
                                    }
                                    "2000" -> {
                                        LogUtil.d("需要输入完整手机号")
                                    }
                                    "0000" -> {
                                        LogUtil.d("可以发起交易")
                                        if (TYPE_TRANS == transType) {
                                            doTransaction(transAmount)
                                        } else if (TYPE_PRE_AUTH == transType) {
                                            doPreAuthTransaction(transAmount)
                                        }
                                    }
                                    else -> {
                                        LogUtil.e("${resp.code}--${resp.msg}")
                                        ToastUtil.showToast(resp.msg)
                                    }
                                }

                            }
                        })


//                        toResultPage()
                    }
                }, R.id.fl_dialog_yes)
                .onClick(Layer.OnClickListener { layer, v ->
                    run {
                        LogUtil.d("取消")
                        layer.dismiss()
                    }
                }, R.id.fl_dialog_no)


        pwdInput = dialogLayer.getView(R.id.ppt_password)
        dialogLayer.onShowListener(object : OnShowListener {
            override fun onShown(layer: Layer) {
                KeyBoardUtils.openKeybord(pwdInput.editText, mContext)
            }

            override fun onShowing(layer: Layer) {
            }

        })
        pwdInput.setPasswordStyle(ContextCompat.getColor(mContext, R.color.color_222B45), 30, 6)
        pwdInput.setOnClickListener { view ->
            pwdInput.editText.setFocusable(true)
            pwdInput.editText.isFocusableInTouchMode = true
            pwdInput.editText.requestFocus()
            KeyBoardUtils.openKeybord(pwdInput.editText, mContext)
        }
    }

    /**
     * 手机号后4为弹框
     */
    private fun showPhoneNoInputDialog(requestParas: RequestModel.TrxDataReq) {
        var pwdInput: PayPasswodInput? = null

        val dialogLayer: DialogLayer = DialogUtils.showViewDialog(mContext, R.layout.layout_dialog_phone_no_input, Gravity.CENTER)
        dialogLayer.cancelableOnTouchOutside(true)
                .onClick(Layer.OnClickListener { layer, v ->
                    run {
                        LogUtil.d("付款")
                        layer.dismiss()
                        val input = pwdInput!!.editText!!.text
                        LogUtil.d("输入手机号后六位为:$input")
                        requestParas.phone_no = "$input"
                        requestParas.rout_md = "2"
                        var jsonString = Gson().toJson(requestParas)
                        viewModel.faceRouter(requestParas).observe(this@PaymentActivity, Observer { resp: TrxDataResp ->
                            run {
                                LogUtil.d(Convert.toJson(resp))
                                if ("0000" == resp.code) {
                                    LogUtil.d("路由选择成功继续发起交易")
                                    if (TYPE_TRANS == transType) {
                                        doTransaction(requestParas.trx_amt)
                                    } else if (TYPE_PRE_AUTH == transType) {
                                        doPreAuthTransaction(requestParas.trx_amt)
                                    }
                                } else {
                                    ToastUtil.showToast(resp.msg)
                                }
                            }
                        })
//                        toResultPage()
                    }
                }, R.id.fl_dialog_yes)
                .onClick(Layer.OnClickListener { layer, v ->
                    run {
                        LogUtil.d("取消")
                        layer.dismiss()
                    }
                }, R.id.fl_dialog_no)


        pwdInput = dialogLayer.getView(R.id.ppt_password)
        dialogLayer.onShowListener(object : OnShowListener {
            override fun onShown(layer: Layer) {
                KeyBoardUtils.openKeybord(pwdInput.editText, mContext)
            }

            override fun onShowing(layer: Layer) {
            }

        })
        pwdInput.setPasswordStyle(ContextCompat.getColor(mContext, R.color.color_222B45), 30, 4)
        pwdInput.setOnClickListener { view ->
            pwdInput.editText.setFocusable(true)
            pwdInput.editText.isFocusableInTouchMode = true
            pwdInput.editText.requestFocus()
            KeyBoardUtils.openKeybord(pwdInput.editText, mContext)
        }
    }

    private fun toResultPage(isSuccess: Boolean, message: String): Any? {
        var result = TypeModel()
        result.isStatus = isSuccess
        result.remark = message
        return ARouter.getInstance().build(ArouterUrl.ACTIVITY_TRANS_RESULT)
                .withSerializable(TransResultActivity.RESULT_DATA, result)
                .navigation()
    }

    /**
     * @type 1-路由索引；2-路由索引+手机号后4位；3-保留使用
     */
    private fun initRequestParams(type: Int): RequestModel.TrxDataReq {
        var params = RequestModel.TrxDataReq()
        params.rout_md = type.toString()
        var timeStamp = DateUtils.getTimeStamp(Date())
        params.bio_rslt = "1"
        params.order_id = "121"
        when (type) {
            1 -> {
                params.xor_salt = timeStamp.substring(4, timeStamp.length - 3) + ((Math.random() * 9 + 1) * 100000).toInt()
            }
            2 -> {
                params.phone_no = "1617"
                params.xor_salt = timeStamp.substring(4, timeStamp.length - 3) + ((Math.random() * 9 + 1) * 100000).toInt()
            }
            3 -> {
                params.phone_no = "18911641617"
            }
            else -> {
                LogUtil.e("未知操作")
            }
        }
        params.trx_loc = coordinate
        params.term_ip = Utils.getIpAddress(mContext)
        return params
    }

    private fun doTransaction(amountToFen: String) {
        var initCseqNo = "000555"
        // 序列号自增
        var cseqNo = SPUtils.getString("CSEQ_NO", initCseqNo)
        cseqNo = String.format("%06d", cseqNo.toInt() + 1)
        SPUtils.putString("CSEQ_NO", cseqNo)

        var transfer = RequestModel.TransReq()
        transfer.msG_ID = "0200"
        transfer.pan = "6214830215995142"
        transfer.prO_COD = "000000"
        transfer.ttxN_AMT = amountToFen
        transfer.cseQ_NO = cseqNo
        transfer.iN_MOD = "911"
        transfer.coN_MOD = "00"
        transfer.piN_CAP_CODE = "12"
        transfer.trM_NO = "01978239"
        transfer.merC_CD = "834491115200003"
        transfer.ccy = "156"
        transfer.piN_DATA = "B13660D14AE38BA5"
        transfer.secuR_INF = "2600000000000000"
        transfer.resE_PRI_60 = "22000064000701"
        transfer.mac = "4441334134334445"
        viewModel.doTransaction(transfer).observe(this, Observer { resp: TransResp ->
            var message = ""
            if ("00" == resp.cpscod) {
                LogUtil.d("交易成功：\n" + Convert.toJson(resp))
                message = "¥ ${amountToYuan(resp.ttxN_AMT)}\n\n交易成功"
                toResultPage(true, message)
            } else {
                LogUtil.d("交易失败")
                message = "交易失败"
                toResultPage(false, message)
            }
        })
    }

    private fun doPreAuthTransaction(amountToFen: String) {
        var initCseqNo = "000555"
        // 序列号自增
        var cseqNo = SPUtils.getString("CSEQ_NO", initCseqNo)
        cseqNo = String.format("%06d", cseqNo.toInt() + 1)
        SPUtils.putString("CSEQ_NO", cseqNo)

        var transfer = RequestModel.TransReq()
        transfer.msG_ID = "0100"
        transfer.pan = "6214830215995142"
        transfer.prO_COD = "030000"
        transfer.ttxN_AMT = amountToFen
        transfer.cseQ_NO = cseqNo
        transfer.iN_MOD = "911"
        transfer.coN_MOD = "06"
        transfer.piN_CAP_CODE = "12"
        transfer.trM_NO = "01978239"
        transfer.merC_CD = "834491115200003"
        transfer.ccy = "156"
        transfer.piN_DATA = "B13660D14AE38BA5"
        transfer.secuR_INF = "2600000000000000"
        transfer.resE_PRI_60 = "22000064000701"
        transfer.mac = "4441334134334445"
        viewModel.doTransaction(transfer).observe(this, Observer { resp: TransResp ->
            var message = ""
            if ("00" == resp.cpscod) {
                LogUtil.d("预授权交易成功：\n" + Convert.toJson(resp))
                var message = "¥ ${amountToYuan(resp.ttxN_AMT)}\n\n预授权交易成功"
                toResultPage(true, message)
            } else {
                LogUtil.d("预授权交易失败")
                message = "预授权交易失败"
                toResultPage(false, message)
            }
        })

    }

}
